#pragma once

#include "vec.h"
#include "stdafx.h"
#include "mat.h"
using namespace std;

/*--------------------    LIGHT SOURCE   ---------------------------------------------------------------------------*/
class LightSource {//abstract
protected:
	vec3 m_ambientIntensity;
	vec3 m_diffuseIntensity;
	vec3 m_specularIntensity;
public:
	LightSource(const vec3& ambient, const vec3 & diffuse, const vec3 specular);
	virtual inline vec3 getAmbient() const { return m_ambientIntensity; }
	virtual inline vec3 getDiffuse() const { return m_diffuseIntensity; }
	virtual inline vec3 getSpecular() const { return m_specularIntensity; }
	virtual inline void setAmbient(vec3 newAmbient) {this->m_ambientIntensity = newAmbient;}
	virtual inline void setDiffuse(vec3 newDiffuse) {this->m_diffuseIntensity = newDiffuse;}
	virtual inline void setSpecular(vec3 newSpecular) {this->m_specularIntensity = newSpecular;}
	virtual vec3 getHitDirection(const vec4& p) const =0;
	virtual ~LightSource() = 0;
	virtual vec4 inline getLocation() const {cout<<"method LightSource::getLocation not implemented"<<endl; return vec4(INFINITE,INFINITE,INFINITE,INFINITE); }
	virtual void translateLocation(const GLfloat & x,const GLfloat & y,const GLfloat & z) const {cout<< "method LightSource::translateLocation() not implemented"<<endl;}
	virtual void rotateAboutX(const GLfloat & angle){cout<<"rotateAboutX not implemented"<<endl;}
	virtual void rotateAboutY(const GLfloat & angle){cout<<"rotateAboutY not implemented"<<endl;}
	virtual void rotateAboutZ(const GLfloat & angle){cout<<"rotateAboutZ not implemented"<<endl;}
};


/*--------------------    LIGHT SOURCE   ---------------------------------------------------------------------------*/
/*--------------------    AMBIENT LIGHT SOURCE   ---------------------------------------------------------------------------*/


// we should also add an ambient light source type here...

/*--------------------    AMBIENT LIGHT SOURCE   ---------------------------------------------------------------------------*/
/*--------------------    POINT LIGHT SOURCE   ---------------------------------------------------------------------------*/
class PointLightSource : public LightSource {
private:
	vec4 m_location;
public:
	PointLightSource(const vec3& ambient, const vec3& diffuse, const vec3& specular, const vec4& location);
	virtual vec4 inline getLocation() const { return m_location; }
	virtual vec3 getHitDirection(const vec4 & p) const;
	void setLocation(vec4 newWorldLocation){m_location = newWorldLocation;}
	virtual void translateLocation(const GLfloat & x,const GLfloat & y,const GLfloat & z) const;
	virtual void rotateAboutX(const GLfloat & angle){m_location = RotateX(angle)*m_location;}
	virtual void rotateAboutY(const GLfloat & angle){m_location = RotateY(angle)*m_location;}
	virtual void rotateAboutZ(const GLfloat & angle){m_location = RotateZ(angle)*m_location;}
};

/*--------------------    POINT LIGHT SOURCE   ---------------------------------------------------------------------------*/
/*--------------------    PARALLEL LIGHT SOURCE   ---------------------------------------------------------------------------*/

class ParallelLightSource : public LightSource {
private:
	vec4 m_direction;
public:
	ParallelLightSource(const vec3& ambient, const vec3& diffuse, const vec3& specular, const vec3 & direction);
	inline vec4 getDirection() const { return m_direction; }
	virtual vec3 getHitDirection(const vec4 & p) const;
	void setDirection(vec3 newWorldDirection){ m_direction = newWorldDirection;}
	virtual void rotateAboutX(const GLfloat & angle){m_direction = RotateX(angle)*m_direction;}
	virtual void rotateAboutY(const GLfloat & angle){m_direction = RotateY(angle)*m_direction;}
	virtual void rotateAboutZ(const GLfloat & angle){m_direction = RotateZ(angle)*m_direction;}
};
/*--------------------    PARALLEL LIGHT SOURCE   ---------------------------------------------------------------------------*/


/*--------------------    WTF GLOBAL SECTION   ---------------------------------------------------------------------------*/
PointLightSource * readPointLightSource();

ParallelLightSource * readParallelLightSource();